package pe.edu.unmsm.juegoia.model.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import pe.edu.unmsm.juegoia.model.JuegoTyAModel;
import static pe.edu.unmsm.juegoia.model.JuegoTyAModel.JUGADOR_1;
import static pe.edu.unmsm.juegoia.model.JuegoTyAModel.JUGADOR_2;
import pe.edu.unmsm.juegoia.model.Posicion;

/**
 *
 * @author Pablo & Marlon
 */
public class JuegoTyAHMModel extends JuegoTyAModel {

    private static final int PESO_COME_NORMAL = 10;
    private static final int PESO_COME_BORDE = 6; // falta
    private static final int PESO_AVANZA_NORMAL = 3;
    private static final int PESO_AVANZA_BORDE = 1;
    // PESOS SI LA FICHA ELEGIDA ES DE LA PRIMERA FILA
    private static final int PESO_FICHA_INICIO_COME_NORMAL = 7; // falta
    private static final int PESO_FICHA_INICIO_COME_BORDE = 5; // falta
    private static final int PESO_FICHA_INICIO_AVANZA_NORMAL = 1;
    private static final int PESO_FICHA_INICIO_AVANZA_BORDE = -1; // falta
    private int nivelMaquina; //0: princ   1: intermedio   2: avanzado
    private Posicion movimientoMaquina = new Posicion();

    // mover humano
    @Override
    public void mover(int x, int y) {

        if (isMovimientoLibreValido(x, y)) { // si el movimiento es permitido

            if (isMovimientoComida(x, y)) {
                if (turnoActual == JUGADOR_1) {
                    numFichasRestantesJ2--;
                } else {
                    numFichasRestantesJ1--;
                }
            } else {
//                int jugador = tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()];
//                tablero[x][y] = jugador;
//                tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()] = 0;
            }


            int jugador = tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()];
            tablero[x][y] = jugador;
            tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()] = 0;
            fichaElegidaUltimo = new Posicion(fichaSeleccionada.getPosX(),
                    fichaSeleccionada.getPosY());
            movElegidoUltimo = new Posicion(x, y);
            calcularMovimiento(JUGADOR_1);

            cambiarTurno();
            fichaSeleccionada = null;


            if (existeGanador()) {
                System.out.println("Ganador Jugador: " + jugadorGanador);
                notifytableroObservers();
            } else {
                notifytableroObservers();
                moverMaquina();
                fichaElegidaUltimoJ2 = new Posicion(fichaSeleccionada.getPosX(),
                        fichaSeleccionada.getPosY());
                movElegidoUltimoJ2 = new Posicion(movimientoMaquina.getPosX(), movimientoMaquina.getPosY());
                calcularMovimiento(JUGADOR_2);
                cambiarTurno();
                if (existeGanador()) {
                    System.out.println("Ganador Jugador: " + jugadorGanador);
                }
                notifytableroObservers();
            }

            // notifytableroObservers();

        } else {
        }
    }

    private void moverMaquina() {
        switch (nivelMaquina) {
            case 0:
                moverRandom();
                break;

            case 1:
                //moverPrimeroElMejor();
                moverIntermedio();
                break;

            case 2:
                //moverRamificacionYPoda();
                break;
        }
    }

    private void moverRandom() {
        List<Posicion> fichasMaquina = getFichasMaquina();
        int random;
        Random r = new Random();
        boolean excepcion;

        do {
            try {
                random = r.nextInt(numFichasRestantesJ2);

                System.out.println(random);

                Posicion ficha = fichasMaquina.get(random);
                setFichaSeleccionada(ficha.getPosX(), ficha.getPosY());

                random = r.nextInt(movimientosValidosTodos.size());

                Posicion movimiento = movimientosValidosTodos.get(random);

                moverFichaMaquina(movimiento.getPosX(), movimiento.getPosY());
                movimientoMaquina = new Posicion(movimiento.getPosX(), movimiento.getPosY());

//                if (tablero[movimiento.getPosX()][movimiento.getPosY()] == JUGADOR_1) {
//                    numFichasRestantesJ1--;
//                }
//
//                tablero[movimiento.getPosX()][movimiento.getPosY()] = JUGADOR_2;
//                tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()] = 0;
                excepcion = false;
            } catch (IllegalArgumentException e) {
                excepcion = true;
            }

        } while (excepcion == true);
    }

    private void moverIntermedio() {
        List<Posicion> fichasMaquina = getFichasMaquina();
        Posicion ficha;
        int posXFicha, posYFicha;
        int posXMov, posYMov;
        float peso = Float.MIN_VALUE;
        float pesoTemporal = Float.MIN_VALUE;
        Posicion movimiento;
        for (int i = 0; i < fichasMaquina.size(); i++) {
            ficha = fichasMaquina.get(i);
            setFichaSeleccionada(ficha.getPosX(), ficha.getPosY());
            posXFicha = ficha.getPosX();
            posYFicha = ficha.getPosY();
            for (int j = 0; j < movimientosValidosTodos.size(); j++) {
                movimiento = movimientosValidosTodos.get(j);
                posXMov = movimiento.getPosX();
                posYMov = movimiento.getPosY();
                if (isFichaSeleccionadaFila(0)) { // la ficha seleccionada es de la primera fila
                    if (isMovComida(posXMov, posYMov)) {
                        if (isMovBorde(posXMov, posYMov)) {
                            if (PESO_FICHA_INICIO_COME_BORDE > pesoTemporal) {
                                pesoTemporal = PESO_FICHA_INICIO_COME_BORDE;
                            }
                        } else { // el movimiento es comida normal
                            if (PESO_FICHA_INICIO_COME_NORMAL > pesoTemporal) {
                                pesoTemporal = PESO_FICHA_INICIO_COME_NORMAL;
                            }
                        }
                    } else { // si solo avanza
                        if (isMovBorde(posXMov, posYMov)) {
                            if (PESO_FICHA_INICIO_AVANZA_BORDE > pesoTemporal) {
                                pesoTemporal = PESO_FICHA_INICIO_AVANZA_BORDE;
                            }
                        } else { // si solo avanza normal
                            if (PESO_FICHA_INICIO_AVANZA_NORMAL > pesoTemporal) {
                                pesoTemporal = PESO_FICHA_INICIO_AVANZA_NORMAL;
                            }
                        }
                    }
                } else { // si la ficha es de cualquier otro lugar
                    if (isMovComida(posXMov, posYMov)) {
                        if (isMovBorde(posXMov, posYMov)) {
                            if (PESO_COME_BORDE > pesoTemporal) {
                                pesoTemporal = PESO_COME_BORDE;
                            }
                        } else { // el movimiento es comida normal
                            if (PESO_COME_NORMAL > pesoTemporal) {
                                pesoTemporal = PESO_COME_NORMAL;
                            }
                        }
                    } else { // si solo avanza
                        if (isMovBorde(posXMov, posYMov)) {
                            if (PESO_AVANZA_BORDE > pesoTemporal) {
                                pesoTemporal = PESO_AVANZA_BORDE;
                            }
                        } else { // si solo avanza normal
                            if (PESO_AVANZA_NORMAL > pesoTemporal) {
                                pesoTemporal = PESO_AVANZA_NORMAL;
                            }
                        }
                    }
                }

                if (pesoTemporal > peso) {
                    peso = pesoTemporal;
                    fichaElegidaUltimoJ2 = fichaSeleccionada;
                    movElegidoUltimoJ2 = movimiento;
                }
            }
        }
//        if (isMovComida(movElegidoUltimo.getPosX(), movElegidoUltimo.getPosY())) {
//            numFichasRestantesJ1--;
//        }
        setFichaSeleccionada(fichaElegidaUltimoJ2.getPosX(), fichaElegidaUltimoJ2.getPosY());
        moverFichaMaquina(movElegidoUltimoJ2.getPosX(), movElegidoUltimoJ2.getPosY());
        movimientoMaquina = new Posicion(movElegidoUltimoJ2.getPosX(), movElegidoUltimoJ2.getPosY());
    }

    private boolean isMovBorde(int posXMov, int posYMov) {
        boolean isMovComidaBorde = false;
        if ((posXMov == 4 && posYMov == 6) || (posXMov == 5 && posYMov == 6)
                || (posXMov == 6 && posYMov == 6) || (posXMov == 6 && posYMov == 5)
                || (posXMov == 6 && posYMov == 4) || (posXMov == 0 && posYMov == 2)
                || (posXMov == 0 && posYMov == 1) || (posXMov == 0 && posYMov == 0)
                || (posXMov == 1 && posYMov == 0) || (posXMov == 2 && posYMov == 0)) {
            isMovComidaBorde = true;
        }
        return isMovComidaBorde;
    }

    private boolean isMovComida(int posXMov, int posYMov) {
        boolean isMovComida = false;
        if (tablero[posXMov][posYMov] == JUGADOR_1) {
            isMovComida = true;
        }
        return isMovComida;
    }

    private List<Posicion> getFichasMaquina() {
        List<Posicion> fichasMaquina = new ArrayList<>();

        for (int i = 0; i < tablero.length; i++) {
            for (int j = 0; j < tablero[i].length; j++) {
                if (tablero[i][j] != null && tablero[i][j] == JUGADOR_2) {
                    fichasMaquina.add(new Posicion(i, j));
                    System.out.println("Posicion x,y: " + i + j);
                }
            }
        }

        System.out.println("Posiciones de la maquina");

        return fichasMaquina;
    }

    @Override
    public void setNivelMaquina(int nivelMaquina) {
        this.nivelMaquina = nivelMaquina;
    }

    private void moverFichaMaquina(int posX, int posY) throws IllegalArgumentException {
        try {
            if (tablero[posX][posY] == JUGADOR_1) {
                numFichasRestantesJ1--;
            }

            tablero[posX][posY] = JUGADOR_2;
            tablero[fichaSeleccionada.getPosX()][fichaSeleccionada.getPosY()] = 0;
        } catch (IllegalArgumentException e) {
            throw e;
        }
    }
}
